home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / ugly / expstr.c < prev    next >
C/C++ Source or Header  |  1996-09-04  |  14KB  |  609 lines

  1. /*
  2.  * ugly/expstr.c
  3.  *
  4.  * ugly expandable-string functions
  5.  *
  6.  * Copyright (C) 1995,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 30-Jun-1996
  23.  * created: 12-Sep-1995
  24.  *
  25.  */
  26.  
  27. #include <ctype.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31.  
  32. #include "utypes.h"
  33. #include "ustring.h"
  34. #include "umemory.h"
  35.  
  36. #define NOEXTERN_UGLY_STRING_H
  37. #include "expstr.h"
  38.  
  39. #if DEBUG_UGLY_EXPSTR
  40. #define D(x) x
  41. #define DEXP "*expstr* "
  42. #else
  43. #define D(x)                    /* nufin */
  44. #endif
  45.  
  46. static void es_null(STRPTR func, STRPTR file, ULONG line)
  47. {
  48.     fprintf(stderr, "\n##\n## panic: es=NULL in %s()\n##   called from %s (%lu)\n##\n",
  49.             func, file, line);
  50. }
  51.  
  52. static void s_null(STRPTR func, STRPTR file, ULONG line)
  53. {
  54.     fprintf(stderr, "\n##\n## panic: string=NULL in %s()\n##   called from %s (%lu)\n##\n",
  55.             func, file, line);
  56. }
  57.  
  58. /*
  59.  *-------------------------------------
  60.  * set/clear expstr
  61.  *-------------------------------------
  62.  */
  63.  
  64. /*
  65.  * set_estr_mem
  66.  *
  67.  * set new mem for es_data
  68.  *
  69.  * params: es........expstr where to assign the new mem to
  70.  *         new_size..new size for data part
  71.  * result: TRUE if all ok, new mem in es->es_data;
  72.  * errors: return FALSE, leave es->es_data untouched
  73.  *
  74.  */
  75. static BOOL do_set_estr_mem(EXPSTR * es, STRPTR new_data, size_t new_size)
  76. {
  77.     BOOL ok = TRUE;
  78.  
  79.     if (new_data) {
  80.  
  81. #if DEBUG_UGLY_EXPSTR == 2
  82.         D(fprintf(stderr, DEXP "set to %lu (%p->%p)\n",
  83.                   new_size, es->es_data, new_data));
  84. #endif
  85.         es->es_size = new_size;
  86.         es->es_data = new_data;
  87.  
  88.     } else
  89.         ok = FALSE;
  90.  
  91.     return (ok);
  92. }
  93.  
  94. BOOL ugly_set_estr_mem(EXPSTR * es, size_t new_size)
  95. {
  96.     return (do_set_estr_mem(es, umalloc(new_size), new_size));
  97. }
  98.  
  99. BOOL ugly_dbg_set_estr_mem(EXPSTR * es, size_t new_size, STRPTR file, ULONG line)
  100. {
  101.     BOOL ok = FALSE;
  102.  
  103.     if (!es)
  104.         es_null("set_estr_mem", file, line);
  105.     else {
  106.         ok = do_set_estr_mem(es,
  107.                              ugly_malloc_tracking(new_size, file, line),
  108.                              new_size);
  109.     }
  110.  
  111.     return (ok);
  112. }
  113.  
  114. /*
  115.  * set_estr
  116.  *
  117.  * set es_data with chars copied from a string
  118.  */
  119. BOOL ugly_set_estr(EXPSTR * es, CONSTRPTR s)
  120. {
  121.     BOOL ok = FALSE;
  122.     size_t new_len = strlen(s) + 1;
  123.     STRPTR old_data = es->es_data;
  124.  
  125.     if ((es->es_size == es->es_step)
  126.         && (es->es_size > new_len)) {
  127.         strcpy(es->es_data, s); /* copy new data */
  128.         es->es_len = new_len;   /* set new len */
  129.         ok = TRUE;
  130.     } else if (set_estr_mem(es, modadj(new_len, es->es_step))) {
  131.  
  132.         strcpy(es->es_data, s); /* copy new & release old data */
  133.         ufreestr(old_data);
  134.  
  135.         es->es_len = new_len;   /* set new len */
  136.         ok = TRUE;
  137.     }
  138.     return (ok);
  139. }
  140.  
  141. BOOL ugly_dbg_set_estr(EXPSTR * es, CONSTRPTR s, STRPTR file, ULONG line)
  142. {
  143.     BOOL ok = FALSE;
  144.  
  145.     if (!es)
  146.         es_null("set_estr_mem", file, line);
  147.     else if (!s)
  148.         s_null("set_estr_mem", file, line);
  149.     else {
  150.         size_t new_len = strlen(s) + 1;
  151.         STRPTR old_data = es->es_data;
  152.  
  153. #if DEBUG_UGLY_EXPSTR == 2
  154.         uglymem_wallcheck("setestr()", file, line);
  155. #endif
  156.  
  157.         if ((es->es_size == es->es_step)
  158.             && (es->es_size > new_len)) {
  159.  
  160.             strcpy(es->es_data, s);     /* copy new data */
  161.             es->es_len = new_len;       /* set new len */
  162.             ok = TRUE;
  163.  
  164.         } else if (ugly_dbg_set_estr_mem(es, modadj(new_len, es->es_step), file, line)) {
  165.  
  166.             strcpy(es->es_data, s);     /* copy new & release old data */
  167.             ufree(old_data);
  168.  
  169.             es->es_len = new_len;       /* set new len */
  170.             ok = TRUE;
  171.         }
  172. #if DEBUG_UGLY_EXPSTR == 2
  173.         uglymem_wallcheck("setestr()", file, line);
  174. #endif
  175.  
  176.     }
  177.  
  178.     return (ok);
  179. }
  180.  
  181. /*
  182.  * clr_estr
  183.  *
  184.  * clear expstr (set es_data to "")
  185.  */
  186. BOOL ugly_clr_estr(EXPSTR * es)
  187. {
  188.     return (set_estr(es, ""));
  189. }
  190.  
  191. BOOL ugly_dbg_clr_estr(EXPSTR * es, STRPTR file, ULONG line)
  192. {
  193. #if DEBUG_UGLY_EXPSTR == 2
  194.     STRPTR s = es->es_data;
  195.     if (!s)
  196.         s = "<null>";
  197.     fprintf(stderr, DEXP "clr_estr(%p,`%s')\n", es, s);
  198.     uglymem_wallcheck("clr_estr()", file, line);
  199. #endif
  200.     return (ugly_dbg_set_estr(es, "", file, line));
  201. }
  202.  
  203. /*
  204.  * set_estrn
  205.  *
  206.  * set expstr with first n chars of string
  207.  */
  208. BOOL set_estrn(EXPSTR * es, CONSTRPTR s, size_t n)
  209. {
  210.     BOOL ok = FALSE;
  211.     STRPTR s1 = NULL;
  212.     size_t len = strlen(s);
  213.  
  214.     if (n > len)
  215.         n = len;
  216.  
  217.     s1 = (STRPTR) umalloc(n + 1);
  218.     if (s1) {
  219.  
  220.         memcpy(s1, s, n);
  221.         s1[n] = 0;
  222.         ok = set_estr(es, s1);
  223.         ufree(s1);
  224.  
  225.     }
  226.     return (ok);
  227. }
  228.  
  229. /*
  230.  *-------------------------------------
  231.  * constructor / destructor
  232.  *-------------------------------------
  233.  */
  234.  
  235. EXPSTR *ugly_dbg_init_estr(size_t step_size, STRPTR file, ULONG line)
  236. {
  237.     EXPSTR *es = ugly_malloc_tracking(sizeof(EXPSTR), file, line);
  238.  
  239.     if (es) {
  240.  
  241.         if (step_size < ES_MIN_MEMSTEP)
  242.             step_size = ES_MIN_MEMSTEP;
  243.         es->es_data = NULL;
  244.         es->es_size = 0;
  245.         es->es_step = step_size;
  246.         if (!clr_estr(es)) {
  247.  
  248.             ufree(es);
  249.             es = NULL;
  250.  
  251.         }
  252.     }
  253.     return (es);
  254.  
  255. }
  256.  
  257. EXPSTR *ugly_init_estr(size_t step_size)
  258. {
  259.     EXPSTR *es = umalloc(sizeof(EXPSTR));
  260.  
  261.     if (es) {
  262.  
  263.         if (step_size < ES_MIN_MEMSTEP)
  264.             step_size = ES_MIN_MEMSTEP;
  265.         es->es_data = NULL;
  266.         es->es_size = 0;
  267.         es->es_step = step_size;
  268.         if (!clr_estr(es)) {
  269.  
  270.             ufree(es);
  271.             es = NULL;
  272.  
  273.         }
  274.     }
  275.     return (es);
  276.  
  277. }
  278.  
  279. VOID del_estr(EXPSTR * es)
  280. {
  281. #if DEBUG_UGLY_EXPSTR
  282.     if (es) {
  283.         if (es->es_data) {
  284. #if DEBUG_UGLY_EXPSTR == 2
  285.             STRARR s[17];
  286.             strncpy(s, es->es_data, 17);
  287.             s[16] = 0;
  288.             D(fprintf(stderr, DEXP "del_estr(%p,`%s')\n", es, s));
  289.             umem_wallcheck("del_estr()");
  290. #endif
  291.         } else {
  292.             D(fprintf(stderr, DEXP "attempt to free null-data-estr\n"));
  293.         }
  294.     } else {
  295. #if DEBUG_UGLY_EXPSTR == 2
  296.         D(fprintf(stderr, DEXP "attempt to free null-estr\n"));
  297. #endif
  298.     }
  299. #endif
  300.  
  301.     if (es) {
  302.  
  303.         ufree(es->es_data);
  304.         es->es_len = 0;
  305.         es->es_size = 0;
  306.         es->es_step = 0;
  307.         ufree(es);
  308.  
  309.     }
  310. }
  311.  
  312. /*
  313.  *-------------------------------------
  314.  * append char/string to expstr
  315.  *-------------------------------------
  316.  */
  317. BOOL ugly_app_estrch(EXPSTR * es, int ch)
  318. {
  319.     BOOL ok = TRUE;
  320.  
  321.     if (es->es_len >= es->es_size) {    /* enough mem left? */
  322.  
  323.         STRPTR old_data = es->es_data;  /* N->remeber old data ptr */
  324.  
  325.         if (set_estr_mem(es,
  326.                          es->es_size + es->es_step)) {  /*    set new mem sucessful? */
  327.  
  328.             strcpy(es->es_data, /*    Y->copy old data */
  329.                    old_data);
  330.             ufree(old_data);    /*       release old data */
  331.  
  332.         } else {
  333.             /*    N->return error */
  334.             ok = FALSE;
  335.         }
  336.     }
  337.     if (ok) {
  338.  
  339.         STRPTR s;
  340.         s = es->es_data;
  341.         s[es->es_len - 1] = ch; /* append new char to expstr */
  342.         s[es->es_len] = 0;
  343.         es->es_len++;           /* incr. expstr length */
  344.  
  345.     }
  346.     return (ok);
  347. }
  348.  
  349. BOOL ugly_dbg_app_estrch(EXPSTR * es, int ch, STRPTR file, ULONG line)
  350. {
  351.     BOOL ok = TRUE;
  352.  
  353.     if (!es) {
  354.         es_null("app_estrch", file, line);
  355.         ok = FALSE;
  356.     } else if (es->es_len >= es->es_size) {     /* enough mem left? */
  357.  
  358.         STRPTR old_data = es->es_data;  /* N->remeber old data ptr */
  359.  
  360.         if (ugly_dbg_set_estr_mem(es,
  361.                                   es->es_size + es->es_step, file, line)) {
  362.             /*    set new mem sucessfully? */
  363.  
  364.             strcpy(es->es_data, /*    Y->copy old data */
  365.                    old_data);
  366.             ufree(old_data);    /*       release old data */
  367.         } else {                /*    N->return error */
  368.             ok = FALSE;
  369.         }
  370.     }
  371.     if (ok) {
  372.  
  373.         STRPTR s;
  374.         s = es->es_data;
  375.         s[es->es_len - 1] = ch; /* append new char to expstr */
  376.         s[es->es_len] = 0;
  377.         es->es_len++;           /* incr. expstr length */
  378.  
  379.     }
  380.     return (ok);
  381. }
  382.  
  383. BOOL ugly_app_estr(EXPSTR * es, CONSTRPTR s)
  384. {
  385.     BOOL ok = TRUE;
  386.  
  387. #if 0
  388.     size_t i;
  389.     for (i = 0; ((s[i]) && ok); i++)
  390.         ok &= ugly_app_estrch(es, s[i]);
  391. #else
  392.     /* faster, but maybe buggy */
  393.     size_t slen = strlen(s);
  394.  
  395.     ok = TRUE;
  396.     if ((es->es_len + slen - 1) >= es->es_size) {   /* enough mem left? */
  397.  
  398.         STRPTR old_data = es->es_data;      /* N->remeber old data ptr */
  399.  
  400.         if (ugly_set_estr_mem(es,
  401.               modadj(es->es_len + slen + 1, es->es_step))) {
  402.                   /*    set new mem sucessful? */
  403.  
  404.             strcpy(es->es_data,     /*    Y->copy old data */
  405.                    old_data);
  406.             ufree(old_data);        /*       release old data */
  407.         } else {            /*    N->return error */
  408.             ok = FALSE;
  409.         }
  410.     }
  411.     if (ok) {
  412.  
  413.         STRPTR ds;
  414.         ds = es->es_data + (es->es_len - 1);
  415.         strcat(ds, s);
  416.         /* append new char to expstr */
  417.         es->es_len += slen; /* incr. expstr length */
  418.         es->es_data[es->es_len - 1] = 0;
  419.  
  420.     }
  421. #endif
  422.     return (ok);
  423. }
  424.  
  425. #if 0
  426. BOOL ugly_dbg_app_estrch(EXPSTR * es, int ch, STRPTR file, ULONG line)
  427. {
  428.     BOOL ok = FALSE;
  429.  
  430.     ok = ugly_app_estrch(es, ch);
  431.  
  432.     return (ok);
  433. }
  434. #endif
  435.  
  436. BOOL ugly_dbg_app_estr(EXPSTR * es, CONSTRPTR s, STRPTR file, ULONG line)
  437. {
  438.     BOOL ok = FALSE;
  439.  
  440.     if (!es)
  441.         es_null("app_estr", file, line);
  442.     else if (!s)
  443.         s_null("app_estr", file, line);
  444.     else {
  445. #if 0
  446.         /* oldy, but goldy - slow, but it works */
  447.         size_t i;
  448.         ok = TRUE;
  449.         for (i = 0; ((s[i]) && ok); i++)
  450.             ok &= ugly_dbg_app_estrch(es, s[i], file, line);
  451. #else
  452.         /* faster, but maybe buggy */
  453.         size_t slen = strlen(s);
  454.  
  455.         ok = TRUE;
  456.         if ((es->es_len + slen - 1) >= es->es_size) {   /* enough mem left? */
  457.  
  458.             STRPTR old_data = es->es_data;      /* N->remeber old data ptr */
  459.  
  460.             if (ugly_dbg_set_estr_mem(es,
  461.                   modadj(es->es_len + slen + 1, es->es_step), file, line)) {    /*    set new mem sucessful? */
  462.  
  463.                 strcpy(es->es_data,     /*    Y->copy old data */
  464.                        old_data);
  465.                 ufree(old_data);        /*       release old data */
  466.             } else {            /*    N->return error */
  467.                 ok = FALSE;
  468.             }
  469.         }
  470.         if (ok) {
  471.  
  472.             STRPTR ds;
  473.             ds = es->es_data + (es->es_len - 1);
  474.             strcat(ds, s);
  475.             /* append new char to expstr */
  476.             es->es_len += slen; /* incr. expstr length */
  477.             es->es_data[es->es_len - 1] = 0;
  478.  
  479.         }
  480. #endif
  481.     }
  482.  
  483.     return (ok);
  484. }
  485.  
  486. /*
  487.  *-------------------------------------
  488.  * get part of expstr
  489.  *-------------------------------------
  490.  */
  491.  
  492. /*
  493.  * todo: handle special cases like
  494.  * get_right_estr( .., "hugo", 99 );
  495.  */
  496.  
  497. /*
  498.  * get_mid_estr
  499.  *
  500.  * get a part from a expstr; compare BASIC's "MID$()"
  501.  *
  502.  * params: dest...destination expstr where to store result part
  503.  *         src....source expstr where to get part from
  504.  *         from...position of char where to begin part (0=first char)
  505.  *         num....number of chars to get
  506.  * result: TRUE and result in dest if ok; else FALSE is returned an
  507.  *         dest is left untouched
  508.  *
  509.  * NOTE: it is possible to use the source-exstr as destination-expstr,
  510.  *       because the result is copied to a temp. expstr before
  511.  *       ( example: get_mid_estr( hugo, hugo, 3, 4 ); )
  512.  */
  513. BOOL get_mid_estr(EXPSTR * dest, EXPSTR * src, size_t from, size_t num)
  514. {
  515.     BOOL ok = FALSE;
  516.     EXPSTR *tmp = init_estr(dest->es_step);
  517.  
  518.     if (tmp) {
  519.  
  520.         STRPTR old_data = tmp->es_data;
  521.  
  522.         /* check size */
  523.         if (from >= src->es_len)
  524.             from = src->es_len - 1;
  525.         if (from + num >= src->es_len)
  526.             num = src->es_len - from - 1;
  527.  
  528.         /* set new mem for tmp */
  529.         ok = set_estr_mem(tmp, modadj(num + 1, tmp->es_step));
  530.  
  531.         if (ok) {
  532.  
  533.             /* copy data */
  534.             strncpy(estr2str(tmp), estr2str(src) + from, num);
  535.             tmp->es_data[num] = 0;
  536.             tmp->es_len = num + 1;
  537.             ufree(old_data);
  538.  
  539.             ok = estrcpy(dest, tmp);
  540.  
  541.         }
  542.         del_estr(tmp);
  543.  
  544.     }
  545.     return (ok);
  546. }
  547.  
  548. /*
  549.  * get_right_estr
  550.  *
  551.  * get right part from a expstr; compare BASIC's "RIGHT$()"
  552.  */
  553. BOOL get_right_estr(EXPSTR * dest, EXPSTR * src, size_t num)
  554. {
  555.     if (num >= src->es_len)
  556.         num = src->es_len - 1;
  557.  
  558.     return (get_mid_estr(dest, src, (src->es_len - num - 1), num));
  559. }
  560.  
  561. /*
  562.  * get_left_estr
  563.  *
  564.  * get left part from a expstr; compare BASIC's "LEFT$()"
  565.  */
  566. BOOL get_left_estr(EXPSTR * dest, EXPSTR * src, size_t num)
  567. {
  568.     return (get_mid_estr(dest, src, 0, num));
  569. }
  570.  
  571. /*
  572.  *-------------------------------------
  573.  * misc. functions
  574.  *-------------------------------------
  575.  */
  576.  
  577. /*
  578.  * ugly_estr2str: convert EXPSTR to conventional string
  579.  *
  580.  * NOTE: this function is replaced by a macro with DEBUG undefined
  581.  */
  582. STRPTR ugly_estr2str(EXPSTR * es)
  583. {
  584.     return (es->es_data);
  585. }
  586.  
  587. /*
  588.  * ugly_estrstrlen: return length of an EXPSTR
  589.  *
  590.  * NOTE: this function is replaced by a macro with DEBUG undefined
  591.  */
  592. size_t ugly_estrlen(EXPSTR * es)
  593. {
  594.     return (es->es_len - 1);
  595. }
  596.  
  597. /* estrcpy: clone EXPSTR */
  598. BOOL estrcpy(EXPSTR * dest, EXPSTR * src)
  599. {
  600.     return (set_estr(dest, estr2str(src)));
  601. }
  602.  
  603. /* estrcat: concat two EXPSTRs */
  604. BOOL estrcat(EXPSTR * dest, EXPSTR * src)
  605. {
  606.     return (app_estr(dest, estr2str(src)));
  607. }
  608.  
  609.